home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / expire.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-31  |  13.5 KB  |  502 lines

  1. /* Expire old messages.
  2.  * Inspired by 'expire.c' by Bernie Roehl.
  3.  * Substantially rewritten for integration into KA9Q NOS,
  4.  * WG7J v1.01 and later
  5.  * by Johan. K. Reinalda, WG7J/PA3DIS, March/April 92
  6.  *
  7.  * Old bid expiry by WG7J, March 92
  8.  */
  9. /* 'expire n' sets the expire interval for n hours.
  10.  * Each time the timer goes off, a new process is started,
  11.  * that expires the old messages...
  12.  *
  13.  * The control file '~/spool/expire.dat' contains lists of
  14.  * filename age
  15.  * where 'filename' is the name of the .txt file under '~/spool/mail'
  16.  * containing the messages (without the .txt extension) and where
  17.  * age = maximum age of message in days.
  18.  *
  19.  * If no age is given, the default age is 21 days.
  20.  *
  21.  * filename can be extended into subdirectories, and can have either
  22.  * '/', '\' or '.' to indicate subdirectories.
  23.  * filename should NOT have the ending '.txt'
  24.  */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <dir.h>
  28. #include <dos.h>
  29. #include <fcntl.h>
  30. #include <sys/stat.h>
  31. #include <sys/timeb.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <time.h>
  35. #include "global.h"
  36. #include "config.h"
  37. #include "timer.h"
  38. #include "proc.h"
  39. #include "bm.h"
  40. #include "files.h"
  41. #include "cmdparse.h"
  42.  
  43. int ExpireActive = 0;
  44. char *ExpireArea = NULLCHAR;
  45. time_t ExpireLast = 0;
  46. extern char *skipwhite __ARGS((char *ptr));
  47. extern char *nntp_name_expansion __ARGS((char *name));
  48.  
  49.  
  50. #ifndef __BORLANDC__
  51.  
  52. time_t mktime __ARGS((struct tm *));
  53.  
  54. /* If you're using BC++ 2.0 or higher, you don't need this,
  55.  * but TCC 2.0 doesn't have it...
  56.  */
  57. /* Simple emulation of the mktime() call (sort-of works :-) )
  58.  * doesn't do any error checking,
  59.  * no timezone adjustments or value adjustments
  60.  * neglects seconds,
  61.  * and might be off by a day for leap year corrections
  62.  * Simply 'sort-a' calculates the number of seconds since 1970 - WG7J
  63.  */
  64. static time_t
  65. mktime(t)
  66. struct tm *t;
  67. {
  68.     static int total[12]={0,31,59,90,120,151,181,212,243,273,304,334};
  69.     int years;
  70.     int leapyears;
  71.     int days;
  72.  
  73.     /* time count start at jan 1, 1970, 00:00 hrs */
  74.     years = t->tm_year - 70;
  75.     /* adjust for leap-years */
  76.     leapyears = (years + 2) / 4;
  77.     if (!((years+70) & 3) && (t->tm_mon < 2))
  78.         --leapyears;
  79.  
  80.     days = years*365L + leapyears + total[t->tm_mon] + t->tm_mday;
  81.  
  82.     return( days*86400L + t->tm_hour*3600L + t->tm_min*60L - 19*3600L);
  83. }
  84. #endif
  85.  
  86. /* Default expiry values: */
  87. #define DEFAULT_AGE 21       /* 21 days from arrival date */
  88. #define MSPHOUR (1000L*60L*60L)
  89. #define MSPMINUTE (1000L*60L)
  90. static struct timer Expiretimer;
  91.  
  92. static void Expireprocess __ARGS((int a,void *v1,void *v2));
  93. void Expiretick __ARGS((void *));
  94. static void expire __ARGS((char *,int));
  95.  
  96. int
  97. doexpire(argc,argv,p)
  98. int argc;
  99. char *argv[];
  100. void *p;
  101. {
  102.     if(argc < 2) {
  103.         tprintf("timer: %lu/%lu hrs\n",
  104.                 read_timer(&Expiretimer)/MSPHOUR,
  105.                 dur_timer(&Expiretimer)/MSPHOUR);
  106.         return 0;
  107.     }
  108.     if(*argv[1] == 'n') {
  109.         Expiretick(NULL);
  110.         return 0;
  111.     }
  112.     /* set the timer */
  113.     stop_timer(&Expiretimer); /* Just in case */
  114.     Expiretimer.func = (void (*)())Expiretick;/* what to call on timeout */
  115.     Expiretimer.arg = NULL;        /* dummy value */
  116.     set_timer(&Expiretimer,atol(argv[1])*MSPHOUR); /* set timer duration */
  117.     start_timer(&Expiretimer);
  118.     return 0;
  119. }
  120.  
  121. void
  122. Expiretick(p)
  123. void *p;
  124. {
  125.     start_timer(&Expiretimer);
  126.     /* Spawn off the process */
  127.     if(!ExpireActive)
  128.         if (newproc("Expiry", 2048, Expireprocess, 0, NULL, NULL, 0) == NULLPROC)
  129.         log (-1, "Couldn't start Expiration process");
  130. }
  131.  
  132. static void
  133. Expireprocess(a,v1,v2)
  134. int a;
  135. void *v1, *v2;
  136. {
  137.     char line[80];
  138.     int age;
  139.     char *cp;
  140.     FILE *ctl;
  141.  
  142.     ExpireActive = 1;
  143.     log(-1,"EXPIRE process started");
  144.     if ((ctl = fopen(Expirefile, "r")) == NULLFILE)    {
  145.         ExpireActive = 0;
  146.         return;
  147.     }
  148.     time (&ExpireLast);
  149.     /* read lines from the control file */
  150.     while(fgets(line, sizeof(line), ctl) != NULLCHAR) {
  151.         pwait(NULL); /* be nice */
  152.         if((*line == '#') || (*line == '\n')) /* comment or blank line */
  153.             continue;
  154.         rip(line);
  155.         age = DEFAULT_AGE;
  156.         /* terminate area name */
  157.         if((cp=strpbrk(line, " \t")) != NULLCHAR) {
  158.             /* there is age info */
  159.             *cp++ = '\0';
  160.             age = atoi(cp);
  161.         }
  162.         pwait(NULL); /* be nice */
  163.     ExpireArea = line;
  164.     nntp_name_expansion (line);
  165.         expire(line,age);
  166.         ExpireArea = NULLCHAR;
  167.     }
  168.     fclose(ctl);
  169.     ExpireActive = 0;
  170. }
  171.  
  172. void
  173. expire(filename,age)
  174. char *filename;
  175. int age;
  176. {
  177.     char file[128], bckfile[128], bckctl[128], *cp;
  178.     char buf[128];
  179.     int keep,copy,expired;
  180.     FILE *old;
  181.     FILE *new;
  182.     long pos;
  183.     time_t now;
  184.     time_t then;
  185.     struct tm t;
  186.     struct let lt;
  187.     long startedat, endedat;
  188.     int entrynum = 1;
  189.  
  190.     /* first replace all '.' and '\' with '/' */
  191.     for(cp=filename;*cp != '\0'; cp++)
  192.         if((*cp == '.') || (*cp == '\\'))
  193.             *cp = '/';
  194.  
  195.     if (mlock(Mailspool,filename)) {
  196.         /* can't get a lock */
  197.         return;
  198.     }
  199.  
  200.     /* rename the old *.ctl file */
  201.     sprintf(file,"%s/CONTROL/%s.ctl",Mailspool,filename);
  202.     sprintf(bckctl,"%s/CONTROL/%s.exp",Mailspool,filename);
  203.     unlink (bckctl);
  204.     if(rename(file,bckctl) == -1) {
  205.         rmlock(Mailspool, filename);
  206.         return;
  207.     }
  208.  
  209.     /* now append the 'home dir' in front of name */
  210.     strcpy(file,Mailspool);
  211.     strcat(file,"/");
  212.     strcat(file, filename);
  213.  
  214.     /* get the name for the backup file */
  215.     strcpy(bckfile,file);
  216.     strcat(bckfile,".exp");
  217.     strcat(file,".txt");
  218.  
  219.     /* rename the file */
  220.     unlink(bckfile);
  221.     if(rename(file,bckfile) == -1) {
  222.         rmlock(Mailspool, filename);
  223.         return;
  224.     }
  225.  
  226.     pwait (NULL);
  227.     /* open the backup file and the new txt file */
  228.     if((old = fopen(bckfile, READ_TEXT)) == NULLFILE) {
  229.         rmlock(Mailspool, filename);
  230.         return;
  231.     }
  232.     if((new = fopen(file, WRITE_TEXT)) == NULLFILE) {
  233.         rmlock(Mailspool, filename);
  234.         return;
  235.     }
  236.     pwait (NULL);
  237.     time(&now);
  238.     copy = expired = 0;
  239.     pos=ftell(old);
  240.     while(fgets(buf,sizeof(buf),old) != NULLCHAR) {
  241.         pwait(NULL);
  242.         if (!strncmp(buf,"From ",5)) {
  243.             /* start of next message; at this point
  244.              * pos has the offset of the start of this line
  245.              */
  246.             keep = copy = 0;
  247.             while(fgets(buf,sizeof(buf),old) != NULLCHAR) {
  248.         pwait (NULL);
  249.                 if(*buf == '\n')
  250.                     break; /* end of headers */
  251.                 if(htype(buf) == DATE) {
  252.                     /* find age from ARPA style date */
  253.                     /* check to see if there is a "Day, " field */
  254.                     if((cp=strchr(buf,',')) != NULLCHAR)  {
  255.                         /* probably standard ARPA style header */
  256.                         cp = &buf[11]; /* get past header and DAY field */
  257.                     } else {
  258.                         /* probably a NNTP style message, that has no
  259.                          * "Day, " part in the date line
  260.                          */
  261.                          cp = &buf[6];
  262.                     }
  263.                     /* now we should be at the start of the
  264.                      * "14 Apr 92 08:14:32" string
  265.                      */
  266.                     if(strlen(cp) < 17) /* Too short */
  267.                         break;
  268.                     t.tm_mday = atoi(cp);
  269.                     if(*(++cp) != ' ')
  270.                         ++cp;
  271.                     ++cp;
  272.                     for(t.tm_mon=0; t.tm_mon < 12; t.tm_mon++)
  273.                         if(strnicmp(Months[t.tm_mon],cp,3) == 0)
  274.                             break;
  275.                     if(t.tm_mon == 12)
  276.                         break; /* invalid */
  277.                     t.tm_year = atoi(cp+4);
  278.                     t.tm_hour = atoi(cp+7);
  279.                     t.tm_min = atoi(cp+10);
  280.                     t.tm_sec = atoi(cp+13);
  281.                     /*
  282.                     printf("%d %d %d, %d %d %d\n",
  283.                     t.tm_mday,t.tm_mon,t.tm_year,t.tm_hour,t.tm_min,t.tm_sec);
  284.                      */
  285.                      if((then=mktime(&t)) == -1)
  286.                         break; /* invalid, delete */
  287.                     /* Now check against age */
  288.                     if(now-then < (age*86400L))
  289.                         keep = 1;
  290.                     break;
  291.                 }
  292.             }
  293.             statusCtl (filename, "exp", <, entrynum, 1);
  294.         if (!keep && (lt.status & BM_PERMANENT))
  295.             keep = 1;        /* don't expire permanent messages */
  296.             if(keep) {
  297.                 /* rewind to start of this message,
  298.                  * write from-line and copy the rest
  299.                  */
  300.                 pwait (NULL);
  301.                 if (lt.status & BM_DELETE)
  302.                     expired++;
  303.                 else    {
  304.                     lt.start = ftell (new);
  305.                     updateCtl (filename, <);
  306.                     fseek(old,pos,SEEK_SET);
  307.                     fgets(buf,sizeof(buf),old);
  308.                     fputs(buf,new);
  309.                     copy = 1;
  310.             }
  311.             } else
  312.                 expired++;
  313.             entrynum++;
  314.         } else { /* Any none 'from' line */
  315.             if(copy)
  316.                 /* we're in the middle of copying a message */
  317.                 fputs(buf,new);
  318.         }
  319.         pwait (NULL);
  320.         pos=ftell(old);
  321.     }
  322.     fclose(new);
  323.     fclose(old);
  324.     pwait (NULL);
  325.     unlink(bckfile);
  326.     unlink (bckctl);
  327.     rmlock(Mailspool,filename);
  328.     if(expired)
  329.         log(-1,"Expired: %d in %s",expired,filename);
  330. }
  331.  
  332.  
  333. void
  334. exp_function(funcname, filename, fname, theage, thetimer, strsize, sortsize)
  335. char *funcname, *filename, *fname;
  336. int theage;
  337. struct timer *thetimer;
  338. int strsize, sortsize;
  339. {
  340. extern int expired;
  341. time_t age;
  342.  
  343.     stop_timer(thetimer);
  344.     log(-1,"%s: processing",funcname);
  345.  
  346.     merge (filename);        /* add in contents of '.new' file */
  347.     age = (time_t)(theage*86400L);
  348.     sortit (filename, strsize + 17, sortsize, strsize,age);    /* sort entire file */
  349.  
  350.     if(expired)
  351.         log(-1,"%s: %d expired",funcname, expired);
  352.     start_timer(thetimer);
  353.     return;
  354. }
  355.  
  356. /******************************************************************/
  357. /* This program will deleted old BID's from the history file,
  358.  * after making a backup copy.
  359.  *
  360.  *  Eg. 'oldbids 24 30' will try to delete all bids older then 30 days
  361.  *      every 24 hours.
  362.  *      'oldbids now' will do it now, with set value of age.
  363.  *
  364.  * Copyright 1992, Johan. K. Reinalda, WG7J/PA3DIS
  365.  *      email : johan@ece.orst.edu
  366.  *      packet: wg7j@wg7j.or.usa.na
  367.  *
  368.  * Any part of this source may be freely distributed for none-commercial,
  369.  * amateur radio use only, as long as credit is given to the author.
  370.  *
  371.  * v1.0 920325
  372.  * Modified to add oldwpages using shared code TNOS 1.0     BAL
  373.  */
  374. static struct timer Oldbidtimer;
  375. static int Oldbid_age = 30;
  376. static struct timer Oldwpagestimer;
  377. static int Oldwpages_age = 30;
  378.  
  379. static void
  380. Oldbidprocess(a,v1,v2)
  381. int a;
  382. void *v1, *v2;
  383. {
  384.     exp_function ("Oldbid", Historyfile, "history", Oldbid_age, &Oldbidtimer, 13, 12);
  385. }
  386.  
  387. void
  388. Oldbidtick(p)
  389. void *p;
  390. {
  391.     if (newproc("Oldbid", 2048, Oldbidprocess, 0, NULL, NULL, 0) == NULLPROC)
  392.         log (-1, "Couldn't start Oldbid process");
  393. }
  394.  
  395. static void
  396. Oldwpagesprocess(a,v1,v2)
  397. int a;
  398. void *v1, *v2;
  399. {
  400.     exp_function ("Oldwpages", WhitePagesBBS, "wpagebbs", Oldwpages_age, &Oldwpagestimer, 32, 6);
  401.     exp_function ("Oldwpages", WhitePages, "wpages", Oldwpages_age, &Oldwpagestimer, 13, 6);
  402. }
  403.  
  404. void
  405. Oldwpagestick(p)
  406. void *p;
  407. {
  408.     if (newproc("Oldwpages", 2048, Oldwpagesprocess, 0, NULL, NULL, 0) == NULLPROC)
  409.         log (-1, "Couldn't start Oldwpages process");
  410. }
  411.  
  412. static char *names[] = {"White Pages", "Bulletin ID"};
  413.  
  414. static int
  415. dotimer(argc,argv,p)
  416. int argc;
  417. char *argv[];
  418. void *p;
  419. {
  420. struct timer *thetimer;
  421. void (*thefunc) ();    /* Function to call at expiration */
  422.  
  423.     thetimer = (p) ? &Oldbidtimer : &Oldwpagestimer;
  424.     thefunc = (p) ? Oldbidtick : Oldwpagestick;
  425.     if(argc < 2){
  426.         tprintf("%s timer: %lu/%lu minutes\n", names[(int)p],
  427.             read_timer(thetimer)/MSPMINUTE,
  428.             dur_timer(thetimer)/MSPMINUTE);
  429.         return 0;
  430.     }
  431.     stop_timer (thetimer);    /* just in case */
  432.     thetimer->func = (void (*)())thefunc;/* what to call on timeout */
  433.     thetimer->arg = NULL;        /* dummy value */
  434.     set_timer(thetimer,atol(argv[1])*MSPMINUTE); /* set timer duration */
  435. //    (*thefunc)(NULL); /* Do one now and start it all!*/
  436.     start_timer(thetimer);     /* fire it up */
  437.     return 0;
  438. }
  439.  
  440. static int
  441. dokick(argc,argv,p)
  442. int argc;
  443. char *argv[];
  444. void *p;
  445. {
  446. void (*thefunc) ();    /* Function to call at expiration */
  447.  
  448.     thefunc = (p) ? Oldbidtick : Oldwpagestick;
  449.     (*thefunc) (NULL);
  450.     return 0;
  451. }
  452.  
  453.  
  454. static int
  455. doage(argc,argv,p)
  456. int argc;
  457. char *argv[];
  458. void *p;
  459. {
  460. int *theage;
  461. void (*thefunc) ();    /* Function to call at expiration */
  462.  
  463.     theage = (p) ? &Oldbid_age : &Oldwpages_age;
  464.     if(argc < 2)
  465.         tprintf("%s age: %d days\n", names[(int)p], *theage);
  466.     else
  467.             *theage = atoi(argv[1]);
  468.     return 0;
  469. }
  470.  
  471.  
  472.  
  473.  
  474. static struct cmds DFAR OLDcmds[] = {
  475.     "age",        doage,        0,    0,    NULLCHAR,
  476.     "kick",        dokick,        0,    0,    NULLCHAR,
  477.     "timer",    dotimer,    0,    0,    NULLCHAR,
  478.     NULLCHAR,
  479. };
  480.  
  481.  
  482. int
  483. dooldbids(argc,argv,p)
  484. int argc;
  485. char *argv[];
  486. void *p;
  487. {
  488.     return (subcmd (OLDcmds, argc, argv, (void *)1));
  489. }
  490.  
  491.  
  492. int
  493. dooldwpages(argc,argv,p)
  494. int argc;
  495. char *argv[];
  496. void *p;
  497. {
  498.     return (subcmd (OLDcmds, argc, argv, (void *)0));
  499. }
  500.  
  501.  
  502.